<?php

namespace Gnway\Ticket\Rest\Util;

use Gnway\Ticket\Rest\Container\RestContainer;
use InvalidArgumentException;
use ReflectionException;

final class MethodUtils
{

  /**
   * Don't let anyone instantiate this class
   */
  private function __construct() {}
  
  /**
   * Invoke a method.
   *
   * @param mixed  $class
   * @param string $method
   * @param array  $parameters
   * @return mixed
   * @throws ReflectionException
   */
  public static function invoke($class, string $method, array $parameters = [])
  {
    is_object($class) || $class = RestContainer::make($class);
    if (!method_exists($class, $method)) {
      throw new InvalidArgumentException('Invoke failed, method "' . $method . '" does not exists');
    }
    if (!self::invokable($class, $method)) {
      throw new InvalidArgumentException('Invoke failed, method "' . $method . '" is not available');
    }

    return $class->$method(...self::getParameters($class, $method, $parameters));
  }

  /**
   * Invokable
   *
   * @param string|object $class
   * @param string|null   $method
   * @return bool
   */
  public static function invokable($class, string $method): bool
  {
    return method_exists($class, $method) && is_callable([$class, $method]);
  }

  /**
   * Resolve the parameters of a specified method.
   *
   * @param string|object $class
   * @param string        $method
   * @param array         $parameters
   * @return array
   * @throws ReflectionException
   */
  public static function getParameters($class, string $method, array $parameters = []): array
  {
    return RestContainer::getMethodParameters($class, $method, $parameters);
  }
}